<html>
   <head>
      <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
   
      <title>5.2. Web Services</title>
      <meta name="generator" content="DocBook XSL-NS Stylesheets V1.75.2">
      <link rel="home" href="indice.html" title="Manual Usuario gvHidra">
      <link rel="up" href="ch05.html" title="Cap&iacute;tulo 5. Fuentes de datos">
      <link rel="prev" href="ch05.html" title="Cap&iacute;tulo 5. Fuentes de datos">
      <link rel="next" href="ch05s03.html" title="5.3. ORM">
   </head>
   <body bgcolor="white" text="black" link="#0000FF" vlink="#840084" alink="#0000FF">
      <div class="navheader">
         <table width="100%" summary="Navigation header">
            <tr>
               <th colspan="3" align="center">5.2. Web Services</th>
            </tr>
            <tr>
               <td width="20%" align="left"><a accesskey="p" href="ch05.html">Anterior</a>&nbsp;
               </td>
               <th width="60%" align="center">Cap&iacute;tulo 5. Fuentes de datos</th>
               <td width="20%" align="right">&nbsp;<a accesskey="n" href="ch05s03.html">Siguiente</a></td>
            </tr>
         </table>
         <hr>
      </div>
      <div class="section" title="5.2. Web Services">
         <div class="titlepage">
            <div>
               <div>
                  <h2 class="title" style="clear: both"><a name="d4e4086"></a>5.2. Web Services
                  </h2>
               </div>
            </div>
         </div>
             
         
             
         <p></p>
         
             
         <div class="itemizedlist">
            <ul class="itemizedlist" type="disc">
               <li class="listitem">
                          
                  <p><a class="link" href="ch05s02.html#wsphp">Web Services en PHP</a></p>
                  
                          
                  <div class="itemizedlist">
                     <ul class="itemizedlist" type="circle">
                        <li class="listitem">
                                       
                           <p><a class="link" href="ch05s02.html#wsphp_cli">Cliente</a></p>
                                     
                        </li>
                     </ul>
                  </div>
                  
                          
                  <div class="itemizedlist">
                     <ul class="itemizedlist" type="circle">
                        <li class="listitem">
                                       
                           <p><a class="link" href="ch05s02.html#wsphp_srv">Servidor</a></p>
                                     
                        </li>
                     </ul>
                  </div>
                        
               </li>
               <li class="listitem">
                          
                  <p><a class="link" href="ch05s02.html#wsdl">Generaci&oacute;n del WSDL</a></p>
                        
               </li>
               <li class="listitem">
                          
                  <p><a class="link" href="ch05s02.html#wsgvh">Web Services en gvHIDRA</a></p>
                  
                          
                  <div class="itemizedlist">
                     <ul class="itemizedlist" type="circle">
                        <li class="listitem">
                                       
                           <p><a class="link" href="ch05s02.html#wsgvh_cli">Cliente</a></p>
                                     
                        </li>
                     </ul>
                  </div>
                  
                          
                  <div class="itemizedlist">
                     <ul class="itemizedlist" type="circle">
                        <li class="listitem">
                                       
                           <p><a class="link" href="ch05s02.html#wsgvh_srv">Servidor</a></p>
                                     
                        </li>
                     </ul>
                  </div>
                        
               </li>
            </ul>
         </div>
         
             
         <div class="section" title="5.2.1. Web Services en PHP">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e4115"></a>5.2.1. Web Services en PHP
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <p><a name="wsphp"></a></p>
            
                  
            <div class="section" title="5.2.1.1. Cliente">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e4118"></a>5.2.1.1. Cliente
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p><a name="wsphp_cli"></a>La creaci&oacute;n de un cliente de un servicio web con
                          PHP es relativamente sencilla haciendo uso de PHP-SOAP. Con la
                          descripci&oacute;n del servicio al que queremos acceder (fichero wsdl),
                          obtendremos acceso a todos los m&eacute;todos que ofrece el servicio web. A
                          continuaci&oacute;n mostramos un ejemplo donde se ver&aacute; m&aacute;s claramente lo
                          expuesto. Concretamente en el ejemplo llamamos a un WS que, dada una
                          cadena, devuelve la cadena al rev&eacute;s.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$objClienteWS = new SoapClient('Ws_Ejemplo.wsdl');
$resultado = $objClienteWS-&gt;ejemplo('Hola');
print_r($resultado);
</pre>
                          </div>
               
                       
               <p>De la ejecuci&oacute;n de este cliente obtenemos el siguiente
                          resultado:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">  aloH</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="5.2.1.2. Servidor">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e4126"></a>5.2.1.2. Servidor
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p><a name="wsphp_srv"></a>La creaci&oacute;n del servidor requiere, evidentemente,
                          algo m&aacute;s de trabajo que la del cliente. En este punto haremos un
                          peque&ntilde;o resumen de los pasos a seguir. Primero tenemos que crear un
                          fichero php (en nuestro ejemplo server.php) que contendr&aacute; las llamadas
                          a las clases SOAP correspondientes al servidor. En este mismo fichero
                          se puede incluir la definici&oacute;n de la clase que implementar&aacute; todos los
                          m&eacute;todos exportados. Siguiendo con nuestro ejemplo, tenemos que tener
                          un m&eacute;todo que nos devuelva la inversa de una cadena. El contenido del
                          fichero es:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">require_once 'SOAP/Server.php';
  
 class Prueba_Server {          
    function ejemplo($cadena){
      return strrev($cadena);
    }    
 }

 $server = new SOAP_Server;
 $server-&gt;_auto_translation = true;
 $soapclass = new Prueba_Server();
 $server-&gt;addObjectMap($soapclass,'urn:Prueba_Server');
 $server-&gt;service($HTTP_RAW_POST_DATA);
</pre>
                          </div>
               
                       
               <p>Para que el cliente tenga acceso a la informaci&oacute;n que ofrece el
                          WS, necesita de la definici&oacute;n de los m&eacute;todos exportados por la clase.
                          Esto se obtiene a partir del fichero WSDL. El fichero de nuestro
                          ejemplo es el siguiente:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">&lt;?xml version="1.0"?&gt;
&lt;definitions name="ServerExample" targetNamespace="urn:ServerExample"
  xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
  xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"
  xmlns:tns="urn:ServerExample"
  xmlns:xsd="http://www.w3.org/2001/XMLSchema"
  xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/"
  xmlns="http://schemas.xmlsoap.org/wsdl/"&gt;

&lt;types xmlns="http://schemas.xmlsoap.org/wsdl/"&gt;&lt;/types&gt;
&lt;message name="ejemploRequest"&gt;
  &lt;part name="cadena" type="xsd:string" /&gt;
&lt;/message&gt;
&lt;message name="ejemploResponse"&gt;
  &lt;part name="cadena" type="xsd:string" /&gt;
&lt;/message&gt;
&lt;portType name="ServerExamplePort"&gt;
  &lt;operation name="ejemplo"&gt;
    &lt;input message="tns:ejemploRequest" /&gt;
    &lt;output message="tns:ejemploResponse" /&gt;
  &lt;/operation&gt;
&lt;/portType&gt;
&lt;binding name="ServerExampleBinding" type="tns:ServerExamplePort"&gt;
 &lt;soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" /&gt;
  &lt;operation name="ejemplo"&gt;
    &lt;soap:operation soapAction="urn:Prueba_Server#prueba_server#ejemplo" /&gt;
     &lt;input&gt;
       &lt;soap:body use="encoded" namespace="urn:Prueba_Server" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;
     &lt;/input&gt;
     &lt;output&gt;
       &lt;soap:body use="encoded" namespace="urn:Prueba_Server" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" /&gt;
     &lt;/output&gt;
  &lt;/operation&gt;
&lt;/binding&gt;
&lt;service name="ServerExampleService"&gt;
 &lt;documentation /&gt;
  &lt;port name="ServerExamplePort" binding="tns:ServerExampleBinding"&gt;
   &lt;soap:address location="http://mi-servidor.es/cin/ws/server/server.php" /&gt;
  &lt;/port&gt;
&lt;/service&gt;
&lt;/definitions&gt;</pre>
                          </div>
               
                       
               <p>Con esto nuestro Web Service ya esta funcionando. Simplemente
                          tenemos que llamarlo desde el cliente.
               </p>
                     
            </div>
                
         </div>
         
             
         <div class="section" title="5.2.2. Generaci&oacute;n del WSDL">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e4135"></a>5.2.2. Generaci&oacute;n del WSDL
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <p><a name="wsdl"></a>Uno de los puntos m&aacute;s costosos de la creaci&oacute;n de un WS
                     en PHP es la generaci&oacute;n del WSDL. Hay una serie de herramientas que te
                     permiten su generaci&oacute;n siempre y cuando rellenes ciertos par&aacute;metros. El
                     propio PEAR::SOAP te facilita un proceso para hacerlo, y es el que vamos
                     a intentar explicar a continuaci&oacute;n.
            </p>
            
                  
            <p>La idea consiste en crear un constructor para nuestra clase y, en
                     &eacute;l, sobrescribir una serie de arrays donde aportaremos la informaci&oacute;n de
                     los m&eacute;todos que exporta una clase. Concretamente se trata de la
                     estructura $this-&gt;__dispatch_map que tendr&aacute; una entrada por cada uno
                     de los m&eacute;todos soportados. Despu&eacute;s, tras las llamadas que realizamos al
                     SOAP_Server tenemos que utilizar una clase de SOAP que nos generar&aacute; el
                     WSDL.
            </p>
            
                  
            <p>El c&oacute;digo para nuestro ejemplo es el siguiente:</p>
            
                  
            <div class="informalexample">
                       
               
                       <pre class="programlisting"> require_once 'SOAP/Server.php';
  
 class Prueba_Server {          
    function Prueba_Server(){
        $this-&gt;__dispatch_map['ejemplo'] =
            array(
                'in' =&gt; array('cadena' =&gt; 'string',
                        ),
                'out' =&gt; array('cadena' =&gt; 'string'),
            );
    }
    function ejemplo($cadena){
      return strrev($cadena);
    }    
 }

 
 $server = new SOAP_Server;
 $server-&gt;_auto_translation = true;
 $soapclass = new Prueba_Server();
 $server-&gt;addObjectMap($soapclass,'urn:Prueba_Server');
 
 if(isset($_REQUEST['wsdl'])){ 
   require_once 'SOAP/Disco.php';
   $disco = new SOAP_DISCO_Server($server,'ServerExample');
   header("Content-type: text/xml");
   echo $disco-&gt;getWSDL();
   return;
 }
 
 $server-&gt;service($HTTP_RAW_POST_DATA);
</pre>
                     </div>
            
                  
            <p>Con este c&oacute;digo, al interrogar al server.php directamente,
                     obtendremos un xml que contiene la definici&oacute;n del WS. Este contenido se
                     almacena en un fichero WSDL y, de ese modo, los clientes podr&aacute;n acceder
                     al servicio.
            </p>
                
         </div>
         
             
         <div class="section" title="5.2.3. Web Services en gvHIDRA">
            <div class="titlepage">
               <div>
                  <div>
                     <h3 class="title"><a name="d4e4143"></a>5.2.3. Web Services en gvHIDRA
                     </h3>
                  </div>
               </div>
            </div>
                  
            
                  
            <p><a name="wsgvh"></a>Ya hemos visto como se implementan los WS en PHP. Para
                     aplicaciones con gvHidra, se han implementado algunas clases que ayudan
                     a la creaci&oacute;n tanto del servidor como del cliente en una aplicaci&oacute;n. De
                     momento se utiliza un procedimiento muy b&aacute;sico para controlar la
                     seguridad.
            </p>
            
                  
            <div class="section" title="5.2.3.1. Cliente">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e4146"></a>5.2.3.1. Cliente
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p><a name="wsgvh_cli"></a>La creaci&oacute;n del cliente se realiza mediante la
                          clase IgepWS_Client. A continuaci&oacute;n mostramos el c&oacute;digo:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$objCIN = IgepWS_Client::getClient('actions/ws/WSCIN.wsdl');
$credencial = IgepWS_Client::getCredential('WSCIN');
$objCIN-&gt;getImporte($credencial,....
</pre>
                          </div>
               
                       
               <p>El par&aacute;metro credencial contiene los par&aacute;metros de validaci&oacute;n
                          v&aacute;lidos para ese cliente WS. Este par&aacute;metro se obtiene consultando los
                          DSNs de la aplicaci&oacute;n. La estructura de la credencial seria la
                          siguiente:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$credencial = array(
               'login'=&gt;'XXXXX',
               'password'=&gt;'XXXXX'
   );
</pre>
                          </div>
               
                       
               <p>Esta clase usa SoapClient, y si necesitamos pasarle otras
                          opciones podemos hacerlo con el par&aacute;metro opcional. En el ejemplo
                          siguiente se modifican las opciones para poder depurar la comunicaci&oacute;n
                          con el servidor. En la <a class="ulink" href="http://www.php.net/manual/en/soapclient.construct.php" target="_top">web de
                             PHP</a> se pueden ver otras opciones posibles.
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$obj = IgepWS_Client::getClient('actions/ws/WSCIN.wsdl', array("exceptions" =&gt; 0, 'trace'=&gt;1, ));
print "&lt;pre&gt;\n";
print "Request :       \n". htmlspecialchars($obj-&gt;__getLastRequest())  ."\n";
print "RequestHeaders :\n". $obj-&gt;__getLastRequestHeaders()             ."\n";
print "Response:       \n". htmlspecialchars($obj-&gt;__getLastResponse()) ."\n";
print "ResponseHeaders:\n". $obj-&gt;__getLastResponseHeaders()            ."\n";
print "Functions:      \n". var_export($obj-&gt;__getFunctions(),true)     ."\n";
print "Types:          \n". var_export($obj-&gt;__getTypes(),true)         ."\n";
print "&lt;/pre&gt;";
</pre>
                          </div>
               
                       
               <p>Para depuraci&oacute;n, tambi&eacute;n puede ser &uacute;til inhabilitar la cache del
                          cliente, ya que as&iacute; podemos ir modificando el wsdl:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">IgepWS_Client::disableCache();</pre>
                          </div>
               
                       
               <p>Si el cliente usa una codificaci&oacute;n distinta a UTF-8 (como ocurre
                          con gvHIDRA que usa latin1), conviene indicarlo en las opciones de
                          conexi&oacute;n y as&iacute; no hay que hacer conversiones explicitas, sino que PHP
                          convierte los par&aacute;metros de entrada desde la codificaci&oacute;n origen a
                          UTF-8, y el resultado lo convierte de UTF-8 a la codificaci&oacute;n
                          indicada. Si no lo indicamos se fija a 'latin1'.
               </p>
               
                       
               <p>Ejemplo:</p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$obj = IgepWS_Client::getClient('actions/ws/WSCIN.wsdl', array("exceptions" =&gt; 0, 'trace'=&gt;1, ));
...
print "Response:\n".htmlspecialchars(utf8_decode($obj-&gt;__getLastResponse()))."\n";
...
</pre>
                          </div>
                     
            </div>
            
                  
            <div class="section" title="5.2.3.2. Servidor">
               <div class="titlepage">
                  <div>
                     <div>
                        <h4 class="title"><a name="d4e4165"></a>5.2.3.2. Servidor
                        </h4>
                     </div>
                  </div>
               </div>
                       
               
                       
               <p><a name="wsgvh_srv"></a>En el caso del servidor, los beneficios son
                          mayores. Tenemos dos clases, una clase est&aacute;tica que genera el c&oacute;digo
                          b&aacute;sico del Servidor y otra que proporciona un comportamiento al
                          servidor propio de una aplicaci&oacute;n gvHidra. La primera de ellas es la
                          clase est&aacute;tica IgepWS_ServerBase. Esta clase simplifica la creaci&oacute;n y
                          el registro de un servidor SOAP de WS. Concretamente, en nuestro
                          fichero de lanzamiento del servidor (t&iacute;picamente server.php), que
                          tiene que estar en el raiz de la aplicaci&oacute;n, tendr&iacute;amos el siguiente
                          c&oacute;digo:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting"> require_once "igep/include/igep_ws/IgepWS_ServerBase.php";
 require_once 'ws/server/WSCIN.php';
 
 IgepWS_ServerBase::registrar('WSCIN');
</pre>
                          </div>
               
                       
               <p>Por otro lado, tenemos que crear la clase que controla el
                          Servidor (en nuestro ejemplo WSCIN). Esta clase, al heredar de
                          IgepWS_Server tiene el mecanismo de validaci&oacute;n ya implementado y el
                          sistema de conexi&oacute;n propio de gvHidra. La &uacute;nica premisa que se exige
                          es que, si se requiere validaci&oacute;n, el m&eacute;todo implementado por el
                          programador debe incluir un par&aacute;metro $credencial que se pasar&aacute; al
                          m&eacute;todo checkCredential para validar su contenido.
               </p>
               
                       
               <p>A continuaci&oacute;n mostramos un ejemplo:</p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">include_once "igep/include/igep_ws/IgepWS_Server.php";
  
class WSCIN extends IgepWS_Server
{
    function __construct()
    {
        $msgs = array(
                '1'=&gt;'Error de conexi&oacute;n. Avise al Servicio de Inform&aacute;tica',
                '2'=&gt;'Error en operaci&oacute;n. Avise al Servicio de Inform&aacute;tica',
        );
        parent::IgepWS_Server('WSCIN', $msgs);
        ...
    }
        
    function getImporte($credencial,$anyox, $dgralx, $numx, $tipo_expx, $numtipo_expx)
    {
      if (!$this-&gt;checkCredential($credencial))
        return $this-&gt;getAuthError();
      $dsn = ConfigFramework::getConfig()-&gt;getDSN('dsn_cin');
      $db = $this-&gt;conectar($dsn);
      if (!$db)
        return $this-&gt;gvhFault('1');
      ...
      return array('implic' =&gt; floatval($res[0]['implic']), 'impadj' =&gt; floatval($res[0]['impadj']));
    }
    ...
}</pre>
                          </div>
               
                       
               <p>Si nuestro servidor acepta varias credenciales, podemos pasarle
                          un vector al constructor del padre:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">parent::IgepWS_Server(array('WSCIN','WSMCMENOR',), $msgs);
</pre>
                          </div>
               
                       
               <p>En las credenciales de los servidores de web services, la
                          contrase&ntilde;a hay que almacenarla con hash. Para ello usar el formulario
                          en igep/include/igep_utils/protectdata.php para obtener los hash de
                          las contrase&ntilde;as, y guardar estas &uacute;ltimas en un lugar seguro, fuera de
                          la aplicaci&oacute;n.
               </p>
               
                       
               <p>El par&aacute;metro con los mensajes de error se utiliza si provocamos
                          los errores (Soap_Fault) con el m&eacute;todo gvhFault, que hace las
                          conversiones necesarias en la codificaci&oacute;n y tiene un par&aacute;metro
                          opcional usado para que nos informe del error en el debug (tener en
                          cuenta que los errores de conexi&oacute;n y los del m&eacute;todo consultar ya se
                          registran en el debug). Por ejemplo:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">return $this-&gt;gvhFault('2','Error consultando tabla');
</pre>
                          </div>
               
                       
               <p>Si queremos restringir alg&uacute;n m&eacute;todo a algunas credenciales,
                          podemos hacerlo con m&eacute;todo checkCredential pas&aacute;ndole la lista de
                          credenciales:
               </p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">if (!$this-&gt;checkCredential($credencial, array('WSMCMENOR',)))
        return $this-&gt;getAuthError();</pre>
                          </div>
               
                       
               <p>Tambi&eacute;n hay que tener precauci&oacute;n cuando hacemos consultas sobre
                          base de datos, que si utilizamos campos calculados o agregados (count,
                          min, ...), el resultado ser&aacute; de tipo string. Si queremos obtener otro
                          tipo tendremos que modificarlo usando la funci&oacute;n floatval para tipo
                          float, intval para tipo int, ... En caso de problemas podemos forzar
                          las conversiones con usando la clase SOAP_Value donde b&aacute;sicamente le
                          indicamos el nombre del atributo, el tipo y el valor.
               </p>
               
                       
               <p>Ejemplo:</p>
               
                       
               <div class="informalexample">
                            
                  
                            <pre class="programlisting">$modulos_usuario = new SOAP_Value('modulos', 'ModulosValidaStruct', $array_con_modulos);
</pre>
                          </div>
               
                       
               <p>Tambi&eacute;n es importante tener en cuenta la codificaci&oacute;n, sobretodo
                          cuando nuestro WS recibe o devuelve campos string que puedan tener
                          car&aacute;cteres especiales.
               </p>
               
                       
               <p>Cuestiones:</p>
               
                       
               <div class="itemizedlist">
                  <ul class="itemizedlist" type="disc">
                     <li class="listitem">
                                    
                        <p>la codificaci&oacute;n usada en los WS es UTF-8, luego habr&aacute; que
                                       hacer las transformaciones necesarias desde/hacia LATIN-1 (la
                                       codificaci&oacute;n usada en gvHIDRA)
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>si queremos retornar una cadena obtenida de la BD o de una
                                       constante en un fichero fuente de PHP, tenemos que transformarla a
                                       utf-8 con utf8_encode($cadena), o mejor usamos el m&eacute;todo
                                       encode.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>si recibimos un par&aacute;metro texto vendr&aacute; en utf-8, luego
                                       tambi&eacute;n habr&aacute; que transformarlo (utf8_decode) a latin-1 para
                                       operar con &eacute;l (concatenar con otras cadenas, almacenar en BD,
                                       ...). Lo podemos hacer con el m&eacute;todo decode.
                        </p>
                                  
                     </li>
                     <li class="listitem">
                                    
                        <p>en caso de problemas tambi&eacute;n podemos hacer las
                                       transformaciones con <a class="ulink" href="http://www.php.net/iconv" target="_top">iconv</a>.
                        </p>
                                  
                     </li>
                  </ul>
               </div>
               
                       
               <p>En caso de problemas con alg&uacute;n tipo de datos conviene consultar
                          la documentaci&oacute;n en <a class="ulink" href="http://www.w3.org/TR/xmlschema-2" target="_top">http://www.w3.org/TR/xmlschema-2</a>.
               </p>
                     
            </div>
                
         </div>
           
      </div>
      <div class="navfooter">
         <hr>
         <table width="100%" summary="Navigation footer">
            <tr>
               <td width="40%" align="left"><a accesskey="p" href="ch05.html">Anterior</a>&nbsp;
               </td>
               <td width="20%" align="center"><a accesskey="u" href="ch05.html">Subir</a></td>
               <td width="40%" align="right">&nbsp;<a accesskey="n" href="ch05s03.html">Siguiente</a></td>
            </tr>
            <tr>
               <td width="40%" align="left" valign="top">Cap&iacute;tulo 5. Fuentes de datos&nbsp;</td>
               <td width="20%" align="center"><a accesskey="h" href="indice.html">Inicio</a></td>
               <td width="40%" align="right" valign="top">&nbsp;5.3. ORM</td>
            </tr>
         </table>
      </div>
   </body>
</html>